#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
检查数据库文件占用情况
找出哪些进程在使用数据库文件
"""

import sys
import os
import subprocess
from pathlib import Path

# 添加项目根目录到Python路径
current_dir = Path(__file__).parent.parent
sys.path.insert(0, str(current_dir))

from src.core.path_manager import path_manager

def check_file_usage_windows(file_path):
    """在Windows上检查文件占用情况"""
    try:
        # 使用handle.exe工具（如果可用）
        result = subprocess.run(['handle.exe', str(file_path)], 
                              capture_output=True, text=True, timeout=10)
        if result.returncode == 0:
            return result.stdout
    except (subprocess.TimeoutExpired, FileNotFoundError):
        pass
    
    try:
        # 使用PowerShell的Get-Process和openfiles
        ps_cmd = f'''
        $file = "{file_path}"
        $processes = @()
        
        # 尝试使用openfiles命令
        try {{
            $openfiles = openfiles /query /fo csv | ConvertFrom-Csv
            $fileProcesses = $openfiles | Where-Object {{ $_.FileName -like "*wmssimple.db*" }}
            foreach ($proc in $fileProcesses) {{
                $processes += "进程: $($proc.'Process Name') (PID: $($proc.ID))"
            }}
        }} catch {{
            Write-Host "无法使用openfiles命令"
        }}
        
        # 检查Python进程
        $pythonProcesses = Get-Process python* -ErrorAction SilentlyContinue
        foreach ($proc in $pythonProcesses) {{
            $processes += "Python进程: $($proc.ProcessName) (PID: $($proc.Id))"
        }}
        
        if ($processes.Count -eq 0) {{
            Write-Host "未找到占用文件的进程"
        }} else {{
            $processes | ForEach-Object {{ Write-Host $_ }}
        }}
        '''
        
        result = subprocess.run(['powershell', '-Command', ps_cmd], 
                              capture_output=True, text=True, timeout=15)
        return result.stdout
        
    except Exception as e:
        return f"检查失败: {e}"

def check_python_modules():
    """检查当前Python进程中加载的数据库相关模块"""
    print("检查当前Python进程中的数据库模块:")
    
    db_modules = []
    for module_name in sys.modules:
        if any(keyword in module_name.lower() for keyword in ['database', 'sqlite', 'sqlalchemy']):
            db_modules.append(module_name)
    
    if db_modules:
        print("已加载的数据库相关模块:")
        for module in sorted(db_modules):
            print(f"  - {module}")
    else:
        print("  未找到数据库相关模块")
    
    # 检查是否有活跃的数据库连接
    try:
        if 'src.models.database.database' in sys.modules:
            db_module = sys.modules['src.models.database.database']
            if hasattr(db_module, 'db_manager'):
                if hasattr(db_module.db_manager, 'engine') and db_module.db_manager.engine:
                    print("  ⚠️  发现活跃的数据库连接 (db_manager.engine)")
                    return True
    except Exception as e:
        print(f"  检查数据库连接时出错: {e}")
    
    return False

def force_close_db_connections():
    """强制关闭数据库连接"""
    print("正在尝试关闭数据库连接...")
    
    try:
        # 关闭全局数据库管理器的连接
        if 'src.models.database.database' in sys.modules:
            db_module = sys.modules['src.models.database.database']
            if hasattr(db_module, 'db_manager'):
                if hasattr(db_module.db_manager, 'engine') and db_module.db_manager.engine:
                    db_module.db_manager.engine.dispose()
                    print("✅ 已关闭 db_manager 连接")
                
                # 清除SessionLocal
                if hasattr(db_module.db_manager, 'SessionLocal'):
                    db_module.db_manager.SessionLocal = None
                    print("✅ 已清除 SessionLocal")
        
        # 强制垃圾回收
        import gc
        gc.collect()
        print("✅ 已执行垃圾回收")
        
        return True
        
    except Exception as e:
        print(f"❌ 关闭连接失败: {e}")
        return False

def check_db_usage():
    """检查数据库使用情况"""
    print("========================================")
    print("数据库文件占用检查")
    print("========================================")
    print()
    
    # 获取数据库文件路径
    db_path = path_manager.get_database_file()
    print(f"数据库文件: {db_path}")
    print(f"文件存在: {'是' if db_path.exists() else '否'}")
    print()
    
    if not db_path.exists():
        print("数据库文件不存在，无需检查占用")
        return
    
    # 检查文件是否可以删除
    print("测试文件访问权限...")
    try:
        # 尝试以独占模式打开文件
        with open(db_path, 'r+b') as f:
            pass
        print("✅ 文件可以正常访问")
    except PermissionError:
        print("❌ 文件被占用，无法独占访问")
    except Exception as e:
        print(f"❌ 文件访问测试失败: {e}")
    
    print()
    
    # 检查当前Python进程中的模块
    has_active_connection = check_python_modules()
    print()
    
    # 检查系统级文件占用
    print("检查系统级文件占用...")
    if os.name == 'nt':  # Windows
        usage_info = check_file_usage_windows(db_path)
        if usage_info:
            print("文件占用信息:")
            print(usage_info)
        else:
            print("未找到详细的文件占用信息")
    else:
        print("非Windows系统，跳过系统级检查")
    
    print()
    
    # 提供解决方案
    print("========================================")
    print("解决方案")
    print("========================================")
    
    if has_active_connection:
        print("发现活跃的数据库连接，建议:")
        print("1. 运行 force_close_connections() 强制关闭连接")
        print("2. 重启Python进程")
        print("3. 确保没有其他Python脚本在运行")
    else:
        print("建议:")
        print("1. 关闭所有可能使用数据库的程序")
        print("2. 检查是否有其他Python进程在运行")
        print("3. 重启命令行窗口")
        print("4. 如果问题持续，重启计算机")

def force_close_connections():
    """强制关闭连接的独立函数"""
    print("========================================")
    print("强制关闭数据库连接")
    print("========================================")
    print()
    
    success = force_close_db_connections()
    
    if success:
        print()
        print("✅ 连接关闭完成，现在可以尝试重新创建数据库")
        print("建议运行: python scripts/init_clean_database.py")
    else:
        print()
        print("❌ 无法完全关闭连接，建议重启Python进程")

if __name__ == "__main__":
    if len(sys.argv) > 1 and sys.argv[1] == "--force-close":
        force_close_connections()
    else:
        check_db_usage() 